package com.fowo.api.controller.shipment;

import com.alibaba.fastjson.JSONObject;
import com.amazon.spapi.client.ApiException;
import com.amazon.spapi.model.fulfillmentinbound.InboundShipmentPlan;
import com.amazon.spapi.model.fulfillmentinbound.InboundShipmentPlanList;
import com.amazon.spapi.model.fulfillmentinbound.TransportContent;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fowo.api.common.model.ImportRow;
import com.fowo.api.common.model.R;
import com.fowo.api.common.util.ResponseUtils;
import com.fowo.api.controller.purchase.vo.WarehouseBinParam;
import com.fowo.api.controller.purchase.vo.warehouseBinInventory;
import com.fowo.api.controller.purchase.vo.wfsShipment;
import com.fowo.api.controller.purchase.vo.wfsinventory;
import com.fowo.api.controller.shipment.entity.*;
import com.fowo.api.controller.shipment.fbainvoice.fbaInvoiceAllocateInventoryAction;
import com.fowo.api.entity.*;
import com.fowo.api.inventory.entity.Inventory;
import com.fowo.api.inventory.service.InventoryBusinessService;
import com.fowo.api.inventory.service.impl.InventoryBusinessServiceImpl;
import com.fowo.api.mapper.WarehouseBinDMapper;
import com.fowo.api.model.fba.shipment.FbaShipmentVo;
import com.fowo.api.model.fba.shipment.product.FbaShipmentProductItemVo;
import com.fowo.api.model.fbaaddress.FBAAddressVo;
import com.fowo.api.model.fbainvoice.FBAInvoiceAllocateInventoryAction;
import com.fowo.api.model.fbainvoice.FBAInvoiceVo;
import com.fowo.api.model.fbainvoice.detail.FBAInvoiceDetailItemVo;
import com.fowo.api.model.listing.father.ListingFatherItemVo;
import com.fowo.api.model.listing.father.ListingFatherSearchParamPo;
import com.fowo.api.model.ship.plans.ShipPlansItemVo;
import com.fowo.api.model.ship.plans.ShipPlansSearchParamPo;
import com.fowo.api.model.ship.plans.sub.ShipPlansSubImportPo;
import com.fowo.api.model.wms.order.WmsOrderVo;
import com.fowo.api.service.*;
import com.fowo.api.service.impl.*;
import com.fowo.api.syncAmazon.api.ShipmentService;
import com.fowo.api.sys.entity.SysFile;
import com.fowo.api.user.model.JwtUserInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.stream.Collectors;

@Tag(name = "发货计划单")
@RequestMapping("/api/ship-plans-D")
@RestController
public class ShipPlansDController {
    @Resource
    private ShipPlansServiceImpl service;
    @Resource
    private ShipPlansSubServiceImpl shipPlansSubService;
    @Resource
    private InventoryBusinessServiceImpl inventoryBusinessService;
    @Resource
    private FBAAddressServiceImpl fbaAddressService;
    @Resource
    private FbaShipmentServiceImpl fbaShipmentService;
    @Resource
    private ShipmentService shipmentService;
    @Resource
    private ListingFatherServiceImpl ListingFatherService;
    @Resource
    private SysCountryServiceImpl sysCountryService;
    @Resource
    private FBAInvoiceServiceImpl fbaInvoiceService;
    @Resource
    private StockOutServiceImpl stockOutService;
    @Resource
    private WmsOrderServiceImpl wmsOrderServiceImpl;
    @Resource
    private NavSellOrderServiceImpl navSellOrderService;
    @Resource
    private WarehouseBinDMapper warehouseBinDMapper;
    @Resource
    private WarehouseBinServiceImpl warehouseBinService;

    @Resource
    private WarehouseServiceImpl warehouseService;
    @Resource
    private fbaInvoiceAllocateInventoryAction fbaInvoiceAllocateInventoryation;
    @Resource
    private AmazonSettlementReportSummaryServiceImpl amazonSettlementReportSummaryService;
    @Operation(summary = "根据货件号和店铺同步")
    @PostMapping("shopAndShipmentCode")
    public R shopAndShipmentCode(@RequestBody wfsShipment model) {
        try {
            shipmentService.getShipments(model.getShopId(),model.getListCode());
        } catch (Exception e) {
            return R.fail("同步失败");
        }
        return R.data(0);
    }

    @PostMapping("reportSummary")
    public void AmazonSettlementReportSummaryService(){
//        amazonSettlementReportSummaryService.kawajisuanfa();
    }

    @Operation(summary = "查询结果")
    @GetMapping
    public R<List<ShipPlansItemVo>> search(ShipPlansSearchParamPo search) {
        JwtUserInfo jwtUserInfo = JwtUserInfo.fromHeader();
        if (jwtUserInfo != null) {
            search.setCurrentUserId(jwtUserInfo.getUserId());
        }
        return R.data(service.search(search));
    }

    @Operation(summary = "新增并且锁库存")
    @PostMapping("fBAInvoiceCreateAndLock")
    @Transactional(rollbackFor = Exception.class)
    public R fBAInvoiceCreate(@Validated @RequestBody FBAInvoiceVo model) throws Exception {
        //新增 getInvoiceStatus
        model.setInvoiceStatus("30");
        Long l = fbaInvoiceService.create(model);
        List<Long> ids=new ArrayList<>();
        //锁库存
        ids.add(l);
        try{

            FBAInvoiceVo voById1 = fbaInvoiceService.getVoById(l);
            //设置仓位
//            setBin(voById1);
            fbaInvoiceAllocateInventoryation.setBin(voById1);
            fbaInvoiceService.locksInventory(l);
            fbaInvoiceService.lockpInventory(l);
            FBAInvoiceVo voById = fbaInvoiceService.getVoById(l);
            //修改为锁库存状态
            voById.setIslockinventory("1");
            fbaInvoiceService.update(voById);
        }catch (Exception e){
            Assert.isTrue(false,e.getMessage());
        };
        return R.data(l);
    }

    private void setBin(FBAInvoiceVo voById) throws Exception {
        List<FBAInvoiceDetailItemVo> invoiceDetailList = voById.getInvoiceDetailList();
        for(int i=0;i<invoiceDetailList.size();i++){
            FBAInvoiceDetailItemVo fbaInvoiceDetailItemVo = invoiceDetailList.get(i);
            WarehouseBinParam search=new WarehouseBinParam();
            search.setWarehouseId(voById.getDeliveryWarehouse());
            if(fbaInvoiceDetailItemVo.getShipmentShop()!=null){
                search.setShopId(Long.valueOf(fbaInvoiceDetailItemVo.getShipmentShop()));
            }
            search.setFnskuName(fbaInvoiceDetailItemVo.getShipmentShopFnsku());
            search.setProductId(fbaInvoiceDetailItemVo.getName());
            List<warehouseBinInventory> wareBinOne = warehouseBinDMapper.getWareBinOne(search);
            if(wareBinOne.size()>0){
                warehouseBinInventory warehouseBinInventory = wareBinOne.get(0);
                fbaInvoiceDetailItemVo.setOutBingId(Long.valueOf(warehouseBinInventory.getId()));
                fbaInvoiceDetailItemVo.setWhbCode(warehouseBinInventory.getStorageBin());
            }else{
                WarehouseBin zancun = warehouseBinService.getOne(Wrappers.<WarehouseBin>query()
                        .lambda().eq(WarehouseBin::getStorageBin, "可用暂存")
                        .eq(WarehouseBin::getWarehouseId, voById.getDeliveryWarehouse()));
                fbaInvoiceDetailItemVo.setOutBingId(Long.valueOf(zancun.getId()));
                fbaInvoiceDetailItemVo.setWhbCode(zancun.getStorageBin());
            }

        }
        fbaInvoiceService.update(voById);
    }

    @Operation(summary = "获取详情")
    @GetMapping("{shopId}")
    public R<List<FBAAddress>> getVoById(@PathVariable Long shopId) {
        List<FBAAddress> list = fbaAddressService.list(Wrappers.<FBAAddress>query().lambda().eq(FBAAddress::getShopId, shopId));
        return R.data(list);
    }



    @Operation(summary = "获取详情")
    @GetMapping("getHead/{shopId}")
    public R getHead(@PathVariable Long shopId) {
        QueryWrapper<ListingFather> queryWrapper=new QueryWrapper();
        queryWrapper.select("principal");
        queryWrapper.eq("shop",shopId);
        queryWrapper.last("limit 1");
        ListingFather one = ListingFatherService.getOne(queryWrapper);
        return R.data(one!=null?one.getPrincipal():"","");
    }
    @Operation(summary = "销售出库单撤回")
    @PostMapping("cancelwfsInvoice")
    @Transactional(rollbackFor = Exception.class)
    public R cancelwfsInvoice(@Validated @RequestBody fbaInvoiceCancel model) throws Exception {
        wmsOrderServiceImpl.cancesendgoods(model);
        return R.data(1);
    }
    @Operation(summary = "获取运输信息")
    @GetMapping("getTransportDetails/{id}")
    public R getTransportDetails(@PathVariable Long id) throws Exception {
        FbaShipmentVo voById = fbaShipmentService.getVoById(id);
        TransportContent transportDetails=new TransportContent();
        try{
             transportDetails = shipmentService.getTransportDetails(voById.getShop(), voById.getShipmentId());
        }catch (Exception e){
            return R.data(transportDetails);
        }
        //返回装箱信息
        return R.data(transportDetails);
    }
    //上传装箱信息
//    @Operation(summary = "上传装箱信息")
//    @PutMapping("putTransportDetails")
//    public R putTransportDetails(@Validated Long id) throws Exception {
//        FbaShipmentVo voById = fbaShipmentService.getVoById(id);
//        shipmentService.putTransportDetails(voById);
//        //返回装箱信息
//        return R.data(1);
//    }
    @Operation(summary = "上传装箱信息")
    @PostMapping("putTransportDetails")
    public R putTransportDetails(@RequestBody FbaShipmentVo model) throws Exception {
        fbaShipmentService.update(model);
        FbaShipmentVo voById = fbaShipmentService.getVoById(model.getId());
        shipmentService.putTransportDetails(voById);
        //返回装箱信息
        return R.data(1);
    }



    @Operation(summary = "发货单作废")
    @PostMapping("cancelInvoice")
    @Transactional(rollbackFor = Exception.class)
    public R cancelInvoice(@Validated @RequestBody fbaInvoiceCancel model) {
        //获取发货单
        FBAInvoice byId = fbaInvoiceService.getById(model.getId());
        Assert.isTrue(byId.getInvoiceStatus().equals("40"),"违规操作");
        //撤销出库单
        if(model.getType().intValue()==2){
            //查询出库单
            StockOut ck003 = stockOutService.getOne(Wrappers.<StockOut>query().lambda()
                    .eq(StockOut::getType, "CK003")
                    .likeLeft(StockOut::getRemark, byId.getInoviceCode()));
            try {
                stockOutService.annul(ck003.getId());
            } catch (Exception e) {
                Assert.isTrue(false,"恢复库存失败");
            }
        }
        //修改发货单状态
        byId.setInvoiceStatus("50");
        fbaInvoiceService.updateById(byId);
        //修改货件状态
        fbaInvoiceService.updateShipment(byId);
        return R.data(1);
    }

    @Operation(summary = "fba货件预览接口")
    @PostMapping("shipmentPreview")
    public R<InboundShipmentPlanListD> shipmentPreview( @RequestBody FbaShipmentVo model) {
        InboundShipmentPlanList shipmentPlan=null;
        SysCountry byId = sysCountryService.getById(model.getShipmentsCountry());
        model.setShipmentsCountry(byId.getCode());

        String collect = model.getList().stream().filter(x -> x.getProductName() == null).map(FbaShipmentProductItemVo::getMsku).collect(Collectors.joining(","));
        Assert.isTrue(collect.isEmpty(),collect+"请先匹配再申报");

        //判断是否已经生成过货件了
        List<FbaShipmentProductItemVo> fbaShipmentProductItemVos = model.getList().stream()
                .filter(x->x.getShipmentPlanSn()!= null).collect(Collectors.toList());
        for(int i=0;i<fbaShipmentProductItemVos.size(); i++){
            FbaShipmentProductItemVo fbaShipmentProductItemVo = fbaShipmentProductItemVos.get(i);
            if(fbaShipmentProductItemVo.getShipmentPlanSn()!=null){
                ShipPlansSub one = shipPlansSubService.getOne(Wrappers.<ShipPlansSub>query().lambda().eq(ShipPlansSub::getOrderSn, fbaShipmentProductItemVo.getShipmentPlanSn()));
                if (one.getGenerateshipment().equals("1")) {
                    return R.fail("已创建货件:"+one.getOrderSn());
                }
            }
        }
        try {
             shipmentPlan = shipmentService.createShipmentPlan(model);
        } catch (ApiException e) {
            e.printStackTrace();
            return R.fail("创建发货计划失败"+ e.getResponseBody());
        }
        //把返回的数据封装
        InboundShipmentPlanListD inboundShipmentPlanListD = getInboundShipmentPlanDS(shipmentPlan,model.getShop());
        return R.data(inboundShipmentPlanListD);
    }

    @NotNull
    private InboundShipmentPlanListD getInboundShipmentPlanDS(InboundShipmentPlanList shipmentPlan,Long shopId) {
        InboundShipmentPlanListD inboundShipmentPlanListD=new InboundShipmentPlanListD();
        for(int i=0;i<shipmentPlan.size();i++){
            InboundShipmentPlan inboundShipmentPlan = shipmentPlan.get(i);
            InboundShipmentPlanD inboundShipmentPlanD=new InboundShipmentPlanD();
            BeanUtils.copyProperties(inboundShipmentPlan,inboundShipmentPlanD);
            inboundShipmentPlanD.setShipmentName(generateShipmentName(i+1));
            InboundShipmentPlanItemListD inboundShipmentPlanItemListD=new InboundShipmentPlanItemListD();
            inboundShipmentPlan.getItems().forEach(X->{
                InboundShipmentPlanItemD InboundShipmentPlanItemD=new InboundShipmentPlanItemD();
                BeanUtils.copyProperties(X,InboundShipmentPlanItemD);
                List<ListingFather> list = ListingFatherService.list(Wrappers.<ListingFather>query().lambda()
                        .eq(ListingFather::getMsku, X.getSellerSKU())
                        .eq(ListingFather::getShop, shopId)
                        .eq(ListingFather::getFnsku, X.getFulfillmentNetworkSKU())
                );
                InboundShipmentPlanItemD.setImg(list.size()>0?list.get(0).getImg():null);
                InboundShipmentPlanItemD.setTitle(list.size()>0?list.get(0).getProductName():null);
                inboundShipmentPlanItemListD.add(InboundShipmentPlanItemD);
            });
            inboundShipmentPlanD.setItems(inboundShipmentPlanItemListD);
            inboundShipmentPlanListD.add(inboundShipmentPlanD);
        }
        inboundShipmentPlanListD.setInboundShipmentPlanList(shipmentPlan);
        return inboundShipmentPlanListD;
    }

    @Operation(summary = "新增货件")
    @PostMapping("createShipment")
    public R<Long> create(@Validated @RequestBody FbaShipmentVoD model) {
        return R.data(() -> fbaShipmentService.create2(model));
    }

    @Operation(summary = "获取仓库")
    @GetMapping("getWarehouse/{id}")
    public R<Warehouse> getWarehouse(@PathVariable Long id) {
        Warehouse byId = warehouseService.getById(id);
        return R.data(() -> byId);
    }

    @Operation(summary = "新增发货单")
    @PostMapping("createInvoice")
    public R<Long> createInvoice(@Validated @RequestBody FBAInvoiceVo model) {
        return R.data(() -> fbaInvoiceService.create2(model));
    }

    @Operation(summary = "新增发货单")
    @PostMapping("createInvoiceAndLockInventory")
    public R<Long> createInvoiceAndLockInventory(@Validated @RequestBody FBAInvoiceVo model) {

        return R.data(() -> fbaInvoiceService.create4(model));
    }

    @Operation(summary = "获取可用库存数量")
    @PostMapping("getAvailableStock")
    public R getAvailableStock(@RequestBody List<inventoryParams> inventoryParams) {
        List<Inventory> list=new ArrayList<>();
        if(inventoryParams.size()==0){
            return R.data(list);
        }

        for(int i=0;i<inventoryParams.size();i++){
            QueryWrapper<Inventory> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("stock_qty");
            queryWrapper.eq("stock_id",inventoryParams.get(0).getStockId());
            com.fowo.api.controller.shipment.entity.inventoryParams inventoryParams1 = inventoryParams.get(i);
            queryWrapper.eq("item_id",inventoryParams1.getProductId());
            if(inventoryParams1.getShopId()!=null){
                queryWrapper.eq("shop_id",inventoryParams1.getShopId());
            }else{
                queryWrapper.isNull("shop_id");
            }
            if(inventoryParams1.getFnSku()!=null){
                if(NumberUtils.isNumber(inventoryParams1.getFnSku())){
                    ListingFather byId = ListingFatherService.getById(inventoryParams1.getFnSku());
                    queryWrapper.eq("fn_sku",byId.getFnsku());
                }else {
                    queryWrapper.eq("fn_sku",inventoryParams1.getFnSku());
                }

            }else{
                queryWrapper.isNull("fn_sku");
            }
            Inventory one = inventoryBusinessService.getOne(queryWrapper);
            if(one!=null){
                one.setId(inventoryParams1.getId());
                list.add(one);
            }else{
                Inventory Inventory=new Inventory();
                Inventory.setId(inventoryParams1.getId());
                list.add(Inventory);
            }
        }
        return R.data(list);
    }

    @Operation(summary = "导入预览")
    @PostMapping("import-preview")
    public R importPreview(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "ext", required = false) String ext
    ) {
        return R.data(() ->
                service.importPreview2(file)
        );
    }

    @PostMapping("import-preview3")
    public R importPreview3(
            @RequestParam("file") MultipartFile file,
            @RequestParam("shopId") Long shopId,
            @RequestParam(value = "ext", required = false) String ext
    ) {
        return R.data(() ->
                service.importPreview3(file,shopId)
        );
    }


    @Operation(summary = "下载模版")
    @GetMapping("import/template")
    public void downloadImportTemplate(HttpServletResponse response)
            throws IOException {
        ResponseUtils.setAttachmentFileName(response, "导入发货计划产品（FBA仓）.xlsx");
        InputStream inputStream = new ClassPathResource(
                "templates/fbafahuo.xlsx"
        )
                .getInputStream();
        StreamUtils.copy(inputStream, response.getOutputStream());
    }

    @Operation(summary = "下载货件模板")
    @GetMapping("import/template2")
    public void downloadImportTemplateCreateShipment(HttpServletResponse response)
            throws IOException {
        ResponseUtils.setAttachmentFileName(response, "CreateShipment.xlsx");
        InputStream inputStream = new ClassPathResource(
                "templates/CreateShipment.xlsx"
        )
                .getInputStream();
        StreamUtils.copy(inputStream, response.getOutputStream());
    }


    synchronized String generateShipmentName(int i){
        StringBuilder st=new StringBuilder("FBA(");
        Date date=new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        // 将日期对象格式化为美国时间格式的字符串  2023-10-30 13:54:33
        String usTime = sdf.format(date);
        st.append(usTime);
        st.append(")");
        st.append("-");
        st.append(i);
        return st.toString();
    }

}
